/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __COLOR_H__
#define __COLOR_H__

#include <math/Vector3.h>

namespace liba
{

class Color // : public math::Vector3<float>
{
public:
	float r, g, b;
	Color()
	{
		r = g = b = 0;
	}
	Color(float r, float g, float b)
	:	r(r), g(g), b(b)
	{}
	Color( const math::Vector3<float>  & vec )
	{
		r = vec.x;
		g = vec.y;
		b = vec.z;
	}

	operator math::Vector3<float> ()const
	{
		return math::Vector3<float>(r, g, b);
	}

	const float * data()const
	{
		return &r;
	}

	float * data()
	{
		return &r;
	}

	const float & data( size_t i )const
	{
		return (&r)[i];
	}

	float & data( size_t i )
	{
		return (&r)[i];
	}

	float & operator[] ( size_t i )
	{
		return data(i);
	}

	const float & operator[] ( size_t i )const
	{
		return data(i);
	}

	bool operator== (const Color & col)const
	{
		return 
			fabs(r - col.r) < std::numeric_limits<float>::epsilon() && 
			fabs(g - col.g) < std::numeric_limits<float>::epsilon() && 
			fabs(b - col.b) < std::numeric_limits<float>::epsilon();
	}

	bool operator!= (const Color & col)const
	{
		return !operator==(col);
	}
	
	Color operator +(const Color & other) const
	{
		return Color(r + other.r, g + other.g, b + other.b);
	}
	
	Color operator -(const Color & other) const
	{
		return Color(r - other.r, g - other.g, b - other.b);
	}
	
	Color operator *(float factor) const
	{
		return Color(r * factor, g * factor, b * factor);
	}
	
	Color operator /(float factor) const
	{
		return Color(r / factor, g / factor, b / factor);
	}
	
	const Color & operator+= (const Color & col)
	{
		r += col.r;
		g += col.g;
		b += col.b;
		return *this;
	}

	const Color & operator-= (const Color & col)
	{
		r -= col.r;
		g -= col.g;
		b -= col.b;
		return *this;
	}

	const Color & operator*= ( const float & f )
	{
		r *= f;
		g *= f;
		b *= f;
		return *this;
	}

	const Color & operator/= ( const float & f )
	{
		r /= f;
		g /= f;
		b /= f;
		return *this;
	}

	template<typename Sym>
	struct ConverterBuffer
		:	public converter::ConverterStaticBuffer<Sym, 28*3>
	{
		typedef converter::ConverterStaticBuffer<Sym, 28*3> StaticBuffer;
		bool convert(const Color & value)
		{
			StaticBuffer::size = converter::simple_print( StaticBuffer::data, value[0] );
			for( int i = 1; i < 3; ++i )
			{
				StaticBuffer::data[StaticBuffer::size++] = ' ';
				StaticBuffer::size += converter::simple_print( StaticBuffer::data + StaticBuffer::size, value[i] );
			}
			return true;
		}
	};

	template<class Sym>
	bool convert(const Sym * be, const Sym * en)
	{
		const Sym * beg = be;
		for( int i = 0; i < 3; ++i )
		{
			beg = converter::simple_convert( beg, en, &operator[](i));
			if( !beg )
				return false;
		}
		return true;
	}
};

} // namespace liba
using namespace liba;

#endif //__COLOR_H__

